﻿#region Using directives

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;

using Weazel.Gezel.Model;
using Weazel.Toad.Application.Items;

#endregion

namespace Weazel.Toad.Application.Controls
{
  [ToolboxItem(true)]
  public partial class GezelModelExplorer : UserControl
  {
    private delegate void UpdateModelTreeViewDelegate();
    private UpdateModelTreeViewDelegate updateModelDelegate;

		private GezelTextFile gezelFileToNavigate = null;

    public GezelModelExplorer()
    {
      InitializeComponent();
      updateModelDelegate = new UpdateModelTreeViewDelegate(updateModelTreeView);

      if (LicenseManager.UsageMode == LicenseUsageMode.Runtime)
      {
        modelTreeView.Nodes.Clear();
				Application.Instance.GezelModelAnalysis.ParsingCompleted += new EventHandler<EventArgs>(GezelModelAnalysis_ParsingCompleted);
        Application.Instance.GezelModelAnalysis.ParsingSucceeded +=new EventHandler<EventArgs>(GezelModelAnalysis_ParsingSucceeded);
      }
		}
		void GezelModelAnalysis_ParsingCompleted(object sender, EventArgs e)
		{
			// clear reference, it will be set again
			// if parsing succeded by the updateModelTreeView()
			// method
			gezelFileToNavigate = null;
		}

    private void updateModelTreeView()
    {
      modelTreeView.SuspendLayout();
      modelTreeView.Nodes.Clear();

      Model model = Application.Instance.GezelModelAnalysis.GezelModel;
			gezelFileToNavigate = Application.Instance.GezelModelAnalysis.GezelTextFile;
			System.Diagnostics.Debug.Assert(gezelFileToNavigate != null, "could not get model to navigate!");

      TreeNode modelNode = new TreeNode("Gezel Model");
      modelNode.ImageIndex = modelNode.SelectedImageIndex = 0;

      foreach (Datapath datapath in model.Datapaths.Values)
      {
        TreeNode datapathNode = new TreeNode(datapath.Name);
        datapathNode.ImageIndex = datapathNode.SelectedImageIndex = 1;
        datapathNode.Tag = datapath;

        foreach (OutPort outport in datapath.OutPorts.Values)
        {
          TreeNode outportNode = new TreeNode(outport.LocalName);
          outportNode.ImageIndex = outportNode.SelectedImageIndex = 3;
          outportNode.Tag = outport;

          datapathNode.Nodes.Add(outportNode);
        }

        foreach (InPort inport in datapath.InPorts.Values)
        {
          TreeNode inportNode = new TreeNode(inport.LocalName);
          inportNode.ImageIndex = inportNode.SelectedImageIndex = 3;
          inportNode.Tag = inport;

          datapathNode.Nodes.Add(inportNode);
        }

        foreach (Signal signal in datapath.Signals.Values)
        {
          TreeNode signalNode = new TreeNode(signal.LocalName);
          signalNode.ImageIndex = signalNode.SelectedImageIndex = 4;
          signalNode.Tag = signal;

          datapathNode.Nodes.Add(signalNode);
        }

        foreach (Register register in datapath.Registers.Values)
        {
          TreeNode registerNode = new TreeNode(register.LocalName);
          registerNode.ImageIndex = registerNode.SelectedImageIndex = 4;
          registerNode.Tag = register;

          datapathNode.Nodes.Add(registerNode);
        }

        foreach (SignalFlowGraph signalFlowGraph in datapath.SignalFlowGraphs.Values)
        {
          TreeNode signalFlowgraphNode = new TreeNode(signalFlowGraph.LocalName);
          signalFlowgraphNode.ImageIndex = signalFlowgraphNode.SelectedImageIndex = 4;
          signalFlowgraphNode.Tag = signalFlowGraph;

          datapathNode.Nodes.Add(signalFlowgraphNode);
        }

        modelNode.Nodes.Add(datapathNode);
      }

      foreach (Controller controller in model.Controllers.Values)
      {
        TreeNode controllerNode = new TreeNode(controller.LocalName);
        controllerNode.ImageIndex = controllerNode.SelectedImageIndex = 2;
        controllerNode.Tag = controller;

        foreach (SignalFlowGraph sfg in controller.SignalFlowGraphs.Values)
        {
          TreeNode sfgNode = new TreeNode(sfg.Name);
          sfgNode.ImageIndex = sfgNode.SelectedImageIndex = 4;
          sfgNode.Tag = sfg;
          controllerNode.Nodes.Add(sfgNode);
        }
        modelNode.Nodes.Add(controllerNode);
      }

      foreach (system system in model.Systems.Values)
      {
        TreeNode systemNode = new TreeNode(system.Name);
        systemNode.ImageIndex = systemNode.SelectedImageIndex = 2;
        systemNode.Tag = system;

        foreach (system.DatapathConnectionInfo connection in system.PortConnections.Values)
        {
          TreeNode datapathNode = new TreeNode(connection.LocalName);
          datapathNode.ImageIndex = datapathNode.SelectedImageIndex = 3;
          systemNode.Nodes.Add(datapathNode);
        }

        foreach (Stimulus stimulus in system.Stimuli.Values)
        {
          TreeNode stimuliNode = new TreeNode(stimulus.LocalName);
          stimuliNode.ImageIndex = stimuliNode.SelectedImageIndex = 4;
          systemNode.Nodes.Add(stimuliNode);
        }

        modelNode.Nodes.Add(systemNode);
      }

      modelNode.ExpandAll();
      modelTreeView.Nodes.Add(modelNode);


      modelTreeView.ResumeLayout();
    }

    private void GezelModelAnalysis_ParsingSucceeded(object sender, EventArgs e)
    {
      Invoke(updateModelDelegate);
    }

    private void modelTreeView_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e)
    {
			if (gezelFileToNavigate != null)
			{
				// make sure tab page is visible
				gezelFileToNavigate.OpenTabPage();

				CommonEntity entity = e.Node.Tag as CommonEntity;

				if (entity != null)
				{
					System.Diagnostics.Debug.Assert(
						entity.StartPosition != null, 
						string.Format("Entity '{0}' does not have a start Position", entity.LocalName));

					gezelFileToNavigate.GotoPosition((int)entity.StartPosition.LineNumber - 1, (int)entity.StartPosition.ColumnNumber - 1);

					//Console.WriteLine("Navigating to {0} on line {1}", entity.LocalName, entity.StartPosition.LineNumber);
				}
			}
    }
  }
}
